
#ifndef YAMLFORMAT_H
#define YAMLFORMAT_H

#include <BDockLayout>
#include <BTreeWidget>
#include <BTextEdit>
#include <BTextFormat>

using namespace BWE;

enum YamlType
{
	YType_None,
	YType_Item,
	YType_Array,
	YType_Map,
	YType_Name,
	YType_Value,
	YType_Annotation,
	YType_Max
};

struct YamlItem : public BThing
{
	YamlItem*	parent = 0;
	YamlType	type = YType_None;
	BString		text;
	int			indent = 0;
	BRange		range;
	BRange		headRange;
	BRange		tailRange;
	BArray<BHolder<YamlItem>>	children;
};

typedef BArray<YamlItem*>		YamlItemArray;
typedef BHolder<YamlItem>		YamlItemHolder;
typedef BArray<YamlItemHolder>	YamlItemHolderArray;

class YamlFormat : public BTextFormat
{
	BOBJECT(YamlFormat);
public:
	YamlFormat(const BString& name = BString());
	~YamlFormat();

	int topItemCount() const;
	YamlItem* topItem(int index);

	virtual void styled(const BStyle* style) override;
	virtual void changed(const BString& text) override;

	virtual const BFont* font(int pos) const;
	virtual const BColor* back(int pos) const;
	virtual const BColor* color(int pos) const;

protected:
	void createTreeWidget();
	void freshTreeWidget();
	BTreeItem* createTreeItem(YamlItem* item);

	YamlItem* insertYamlItem(int pos, int count, YamlType type, YamlItem* parent = 0);

	bool readDocument(const BString& xmltext);

	int readIndent(const BString& text);
	YamlItem* upperItem(int indent);
	void arrangeIndent(YamlItem* item);
	BRange trimmedString(const BString& text, int begin, int end);

	BThing* readArray(YamlItem* item, const BString& line, int pos);
	BThing* readMap(YamlItem* item, const BString& line, int pos);

protected:
	void slotAssetChanged(BObject* object, const BValue& value);
	void slotTextEditFramed(BTextEdit* textEdit, const BValue& value);

private:
	BTextEdit*				_textEdit;
	BHolder<BDockLayout>	_dockLayout;
	BTreeWidget*			_treeWidget;
	const BStyle*			_style;
	BMap<YamlType, BColor>	_colorMap;

	BString					_version;
	YamlItemHolderArray		_topItems;
	BMap<int, YamlItem*>	_itemMap;
};

#endif
